# -*- coding: utf-8 -*-
# @Author: bao
# @Date:   2017-02-17 11:20:24
# @Last Modified by:   bao
# @Last Modified time: 2017-05-14 19:22:58

import munkres
import networkx as nx


def get_degree_key(item):
	return item[1]['degree']


def get_weight(weight):
    integral = int(weight)
    fractional = weight - integral
    if not integral:
        return 1
    else:
        if fractional < 0.5:
            return integral
        else:
            return integral + 1


def get_cd(location, row_size):
	"""
    calculate the coordinate
    """
	axis_x = location % row_size
	if axis_x == 0:
		axis_x = row_size
		axis_y = location / row_size
	else:
		axis_y = location / row_size + 1
	return axis_x, axis_y


def get_cp(cd_src, cd_dst, row_size, base_len):
	"""
	get the cp of src and dst
	"""
	if cd_src[0] == cd_dst[0] or cd_src[1] == cd_dst[1]:
		Is_same_axis = True
		cp_x = 0
		cp_y = 0
	else:
		Is_same_axis = False
		cp_x = cd_dst[0] + (cd_src[1] - 1) * row_size + base_len
		cp_y = cd_src[0] + (cd_dst[1] - 1) * row_size + base_len

	return Is_same_axis, cp_x, cp_y


class gen_topo(object):
	"""
    Calculate new topology
    Wavelength assignment and adjustment
    Four steps:
    1) Generate new topology by transforming the traffic matrix into wavelengh matrix by max_weight_matches
    2) Decomposing the graph to matches based on pre_matches (minimal wavelength adjustment)
    3) Assigning colors to maxmize the overlap
    """
	def __init__(self):
		self.pre_matches = {}  # {port:[(src1,dst1), (src2,dst2)]}

	def _transform(self, wl_graph, tf_graph, degree, base_len):
		"""
		Generate the new topology based on traffic demand matrix (tf_graph)
		Max weight matches
		"""
		pass

	def _matchings(self, graph, pre_matches, max_degree, base_len):
		"""
		Minimal Wavelength Adjustment (MWA) based on pre_matches
		Extending the algorithms from paper "WaveCube: A scalable, fault-tolerant, high-performance optical data center architecture"
		"""
		pass

	@staticmethod
	def _color_assignment(pre_matches, cur_matches, base_len):
		"""
		Based on the Hungarian to minimize the wavelength adjustment
		Return dynamic match, static match and new match
		"""
		s_matches = {}  # {port:[(src1,dst1), (src2,dst2)]}
		d_matches = {}  # {port:[(src1,dst1), (src2,dst2)]}
		new_matches = {}  # {port:[(src1,dst1), (src2,dst2)]}
		cost_matrix = []
		# (i,j) means the same edges of pre_matches[i] and cur_matches[j]
		for i in xrange(0, len(pre_matches)):
			cost_matrix.append(i)
			cost_matrix[i] = []
			for j in xrange(0, len(cur_matches)):
				cost_matrix[i].append(base_len - len(set(pre_matches[i + 1]) & set(cur_matches[j + 1])))

		# Calculating the minimize wavelength adjustment
		m = munkres.Munkres()
		indexes = m.compute(cost_matrix)
		# Assign colors to get new matches
		index = 0
		for i in pre_matches:
			if index < len(indexes):
				if i == indexes[index][0] + 1:
					new_matches[i] = cur_matches[indexes[index][1] + 1][:]
					d_matches[i] = list(set(cur_matches[indexes[index][1] + 1]) - set(pre_matches[i]))
					s_matches[i] = list(set(cur_matches[indexes[index][1] + 1]) & set(pre_matches[i]))
					index += 1
				else:
					s_matches[i] = pre_matches[i]
					new_matches[i] = pre_matches[i]
			else:
				s_matches[i] = pre_matches[i]
				new_matches[i] = pre_matches[i]
		return d_matches, s_matches, new_matches
